package com.qlmy.cn.utils

import android.app.Activity
import android.content.Context
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.lifecycleScope
import com.qlmy.cn.api.ApiRequest
import com.qlmy.cn.api.uiScope
import com.qlmy.cn.bean.ImageUploadBean
import com.qlmy.cn.bean.UploadDataBean
import com.qlmy.cn.commom.toColor
import com.qlmy.cn.commom.toastMessageLong
import com.qlmy.cn.commom.tryClose
import com.qlmy.cn.ui.dialog.LoadingDialog
import com.qlmy.cn.ui.dialog.safeDismissDialog
import com.qlmy.cn.ui.dialog.safeShowDialog
import com.wbs.shop.nuby.R
import com.yanzhenjie.album.Album
import com.yanzhenjie.album.AlbumFile
import com.yanzhenjie.album.api.widget.Widget
import kotlinx.coroutines.CoroutineScope
import top.zibin.luban.Luban
import java.io.FileInputStream
import java.security.MessageDigest
import java.util.*


typealias onUploadSuccessListener = ((MutableList<ImageUploadBean>) -> Unit)?
typealias onCancelSuccessListener = (() -> Unit)?

class ImageUploadUtils : LifecycleObserver {
    companion object {
        private val MIME_TYPE = mutableListOf("image/jpg", "image/jpeg", "image/png", "image/JPG", "image/JPEG", "image/PNG")
        private const val MIN_SIZE = (20 * 1024).toLong()
    }

    constructor(activity: FragmentActivity, mOnUploadSuccessListener: onUploadSuccessListener) : super() {
        activity.lifecycle.addObserver(this)
        this.activity = activity
        this.mOnUploadSuccessListener = mOnUploadSuccessListener
        initView()
    }

    constructor(fragment: Fragment, mOnUploadSuccessListener: onUploadSuccessListener) : super() {
        fragment.lifecycle.addObserver(this)
        this.fragment = fragment
        this.mOnUploadSuccessListener = mOnUploadSuccessListener
        initView()
    }

    private var activity: FragmentActivity? = null
    private var fragment: Fragment? = null
    private var mLoadingDialog: LoadingDialog? = null
    private lateinit var mWidget: Widget
    private lateinit var mBuilder: ImageUploadUBuilder
    private var mOnUploadSuccessListener: onUploadSuccessListener = null
    var mOnCancelSuccessListener: onCancelSuccessListener = null

    //    private lateinit var mQcloudUpload: QcloudUpload
    private fun initView() {
        getActivity()?.let {
            mLoadingDialog = LoadingDialog(it)
            mLoadingDialog?.setCancelable(false)
            mWidget = Widget.newDarkBuilder(it)
                    .statusBarColor(R.color.main_color.toColor())
                    .toolBarColor(R.color.main_color.toColor())
                    .bucketItemCheckSelector(R.color.text_hint_color_2.toColor(), R.color.main_color.toColor())
                    .mediaItemCheckSelector(R.color.text_hint_color_2.toColor(), R.color.main_color.toColor())
                    .build()
            /*mQcloudUpload = QcloudUpload(object : OnFileUploadListener {
                override fun onStart() {
                    mLoadingDialog?.safeShowDialog()
                }

                override fun onSuccess(cosPath: MutableList<ImageUploadBean>) {
                    getCoroutineScope()?.launch {
                        if (mBuilder.md5) {
                            cosPath.forEach {
                                it.md5 = getFileMD5(it.originalFile)
                            }
                        }
                        mOnUploadSuccessListener?.invoke(cosPath)
                        mLoadingDialog?.safeDismissDialog()
                    }
                }

                override fun onFail(e: Throwable?) {
                    "上传失败".toastMessageLong()
                    Logger.e(e)
                    mLoadingDialog?.safeDismissDialog()
                }

                override fun onPublishProgress(progress: Int) = it.runOnUiThread { mLoadingDialog?.setProgress(progress) }
            })*/
        }
    }

    fun selectImage(builder: ImageUploadUBuilder) {
        mLoadingDialog?.safeShowDialog()
        mBuilder = builder
        val content = getContext() ?: return
        if (mBuilder.isMultipleChoice) {
            Album.image(content)
                    .multipleChoice()
                    .selectCount(mBuilder.selectCount)
                    .afterFilterVisibility(false)
                    .camera(true)
                    .columnCount(mBuilder.columnCount)
                    .filterMimeType { attributes: String? -> !MIME_TYPE.contains(attributes) }
                    .filterSize { attributes: Long -> attributes < MIN_SIZE }
                    .widget(mWidget)
                    .onResult(this::onAction)
                    .onCancel(this::onCancel)
                    .start()
        } else {
            Album.image(content)
                    .singleChoice()
                    .afterFilterVisibility(false)
                    .camera(true)
                    .columnCount(mBuilder.columnCount)
                    .filterMimeType { attributes: String? -> !MIME_TYPE.contains(attributes) }
                    .filterSize { attributes: Long -> attributes < MIN_SIZE }
                    .widget(mWidget)
                    .onResult(this::onAction)
                    .onCancel(this::onCancel)
                    .start()
        }
    }

    fun onAction(result: ArrayList<AlbumFile>) {
        if (result.isNotEmpty()) {
            val srcPaths = mutableListOf<UploadDataBean>()
            result.forEach { srcPaths.add(UploadDataBean(it.path, it.path)) }
            if (mBuilder.isCompress) { // 是否压缩
                val compressPaths = mutableListOf<String>()
                result.forEach { compressPaths.add(it.path) }
                mLoadingDialog?.safeShowDialog()
                ApiRequest(uiScope()).launchUI({
                    Luban.with(getActivity())
                            .ignoreBy(100)
                            .setFocusAlpha(true)
                            .load(compressPaths)
                            .get()
                            .forEachIndexed { index, file -> srcPaths[index].compressFile = file.path }
                    doAction(srcPaths)
                }, error = {
                    "压缩失败".toastMessageLong()
                    mLoadingDialog?.dismiss()
                })
            } else doAction(srcPaths)
        }
    }

    fun doAction(result: MutableList<UploadDataBean>) {
        if (mBuilder.isUp) {
            if (mBuilder.isMultipleChoice) {
                handFile(result)
            } else {
                if (mBuilder.cutOut) { // 开启剪裁
//                    cutOut(result[0])
                } else {
                    handFile(result)
                }
            }
        } else {
            mLoadingDialog?.dismiss()
            val imageUploads = mutableListOf<ImageUploadBean>()
            result.forEach {
                val mImageUploadBean = ImageUploadBean(filePath = it.compressFile, originalFile = it.originalFile)
                if (mBuilder.md5) {
                    mImageUploadBean.md5 = getFileMD5(it.originalFile)
                }
                imageUploads.add(mImageUploadBean)
            }
            mOnUploadSuccessListener?.invoke(imageUploads)
        }
    }

    private fun onCancel(result: String) {
        mLoadingDialog?.safeDismissDialog()
        mOnCancelSuccessListener?.invoke()
    }

    private fun handFile(result: MutableList<UploadDataBean>) {

        //mQcloudUpload.upload(result)
    }

    fun gallery(gallery: ArrayList<String>, currentPosition: Int) {
        val content = getContext() ?: return
        Album.gallery(content)
                .currentPosition(currentPosition)
                .checkedList(gallery)
                .checkable(false)
                .widget(
                        Widget.newDarkBuilder(content)
                                .statusBarColor(ContextCompat.getColor(content, R.color.main_color))
                                .toolBarColor(ContextCompat.getColor(content, R.color.main_color))
                                .title(R.string.text_preview)
                                .build()
                )
                .start()
    }

    private fun getCoroutineScope(): CoroutineScope? = when {
        activity != null -> activity?.lifecycleScope
        fragment != null -> fragment?.lifecycleScope
        else -> null
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    private fun onDestroy() {
        activity?.lifecycle?.removeObserver(this)
        fragment?.lifecycle?.removeObserver(this)
        activity = null
        fragment = null
        mOnUploadSuccessListener = null
        mLoadingDialog?.safeDismissDialog()
        mLoadingDialog = null
    }

    private fun getContext(): Context? = if (activity != null) activity else fragment?.context

    private fun getActivity(): Activity? = if (activity != null) activity else fragment?.activity

    fun getFileMD5(file: String): String? {
        var digest: MessageDigest? = null
        var fis: FileInputStream? = null
        val buffer = ByteArray(1024)
        var len: Int
        try {
            digest = MessageDigest.getInstance("MD5")
            fis = FileInputStream(file)
            while (fis.read(buffer, 0, 1024).also { len = it } != -1) {
                digest.update(buffer, 0, len)
            }
            return HrHex.encode(digest.digest())
        } catch (e: Exception) {
            return null
        } finally {
            fis?.tryClose()
        }
    }
}

fun ImageUploadUtils.selectImage(imageUploadUBuilder: ImageUploadUBuilder.() -> Unit) {
    selectImage(ImageUploadUBuilder().also(imageUploadUBuilder))
}

class ImageUploadUBuilder {
    var cutOut = false
    var isMultipleChoice = true
    var isUp = false
    var isCompress = true
    var selectCount = 9
    var columnCount = 3
    var md5 = false
}

/*
class QcloudUpload(private val mOnFileUploadListener: OnFileUploadListener) {
    companion object {
        const val ENDPOINT = "http://oss-cn-zhangjiakou.aliyuncs.com"
        private const val P_BUCKETNAME = "blbk"
        private var DOMAIN = ""
    }

    private val simpleDateFormat: SimpleDateFormat = SimpleDateFormat("yyyyMMdd")
    private var mOSSClient: OSSClient? = null
    private lateinit var cosPaths: MutableList<ImageUploadBean>
    private var srcPaths: MutableList<UploadDataBean> = mutableListOf()
    private var fileCount = 0
    private var isSign = false
    fun init() {
        val credentialProvider: OSSCredentialProvider = object : OSSFederationCredentialProvider() {
            override fun getFederationToken(): OSSFederationToken? {
                return SERVICE.gtSts().execute().body()?.data?.run { OSSFederationToken(accessKey, accessSecret, token, expiration) }
            }
        }
        val conf = ClientConfiguration()
        conf.connectionTimeout = 15 * 1000 // 连接超时，默认15秒
        conf.socketTimeout = 15 * 1000 // socket超时，默认15秒
        conf.maxConcurrentRequest = 5 // 最大并发请求数，默认5个
        conf.maxErrorRetry = 2 // 失败后最大重试次数，默认2次
        OSSLog.enableLog() //这个开启会支持写入手机sd卡中的一份日志文件位置在SDCard_path\OSSLog\logs.csv
        mOSSClient = OSSClient(App.app, ENDPOINT, credentialProvider, conf)
    }

    fun upload(srcPaths: MutableList<UploadDataBean>) {
        if (srcPaths.isEmpty()) return
        this.srcPaths = srcPaths
        mOnFileUploadListener.onStart()
        cosPaths = ArrayList<ImageUploadBean>()
        fileCount = srcPaths.size
        isSign = srcPaths.size == 1
        if (mOSSClient == null) {
            ApiRequest(uiScope()).launchUI({
                withContext(Dispatchers.IO) { init() }
                if (mOSSClient != null) {
                    doUpload()
                }
            })
//            BackgroundCommonApi.getQiniuToken { qiNiuToken: String, domain: String ->
//                if (qiNiuToken.isNotEmpty()) {
//                    mToken = qiNiuToken
//                    DOMAIN = domain
//                    doUpload()
//                } else mOnFileUploadListener.onFail(RuntimeException("获取token失败"))
//            }
        } else doUpload()
    }

    private fun doUpload() {
        if (srcPaths.size < 1) return
        val data = srcPaths[0]
        val currentFileName = String.format("%s/taskpic%d.%s", simpleDateFormat.format(Date()), System.currentTimeMillis(), getFileExtension(data.originalFile))
        val putObjectRequest = PutObjectRequest(P_BUCKETNAME, currentFileName, data.compressFile)
        putObjectRequest.progressCallback = OSSProgressCallback { request, currentSize, totalSize ->
            if (fileCount == 1) {
                val fp = currentSize.toFloat() / totalSize.toFloat()
                val progress = (fp * 100).toInt()
//                Logger.e("progress==>$progress")
                mOnFileUploadListener.onPublishProgress(progress)
            }
        }
        mOSSClient?.asyncPutObject(putObjectRequest, object : OSSCompletedCallback<PutObjectRequest?, PutObjectResult?> {
            override fun onSuccess(request: PutObjectRequest?, result: PutObjectResult?) {
                try {
                    Logger.e("================>onSuccess")
                    val imageUploadBean = ImageUploadBean()
                    imageUploadBean.filePath = data.compressFile
                    imageUploadBean.originalFile = data.originalFile
                    imageUploadBean.url = mOSSClient?.presignPublicObjectURL(P_BUCKETNAME, currentFileName)
                    cosPaths.add(imageUploadBean)
                    srcPaths.removeAt(0)
                    try {
                        mOnFileUploadListener.onPublishProgress(BigDecimal(cosPaths.size).divide(BigDecimal(fileCount), 2, RoundingMode.HALF_UP).multiply(BigDecimal(100)).toInt())
                    } catch (e: java.lang.Exception) {
                        Logger.e(e)
                    }
                    if (srcPaths.size == 0) {
                        mOnFileUploadListener.onSuccess(cosPaths)
                        if (!isSign) mOnFileUploadListener.onPublishProgress(100)
                    } else doUpload()
                } catch (e: java.lang.Exception) {
                    Logger.e(e)
                    mOnFileUploadListener.onFail(e)
                }
            }

            override fun onFailure(request: PutObjectRequest?, clientException: ClientException, serviceException: ServiceException) {
                Logger.e("onFailure")
                mOnFileUploadListener.onFail(RuntimeException(clientException))
            }
        })
    }

    fun getFileExtension(filePath: String): String? {
        if (isSpace(filePath)) return ""
        val lastPoi = filePath.lastIndexOf('.')
        val lastSep = filePath.lastIndexOf(File.separator)
        return if (lastPoi == -1 || lastSep >= lastPoi) "" else filePath.substring(lastPoi + 1)
    }

    private fun isSpace(s: String?): Boolean {
        if (s == null) return true
        var i = 0
        val len = s.length
        while (i < len) {
            if (!Character.isWhitespace(s[i])) {
                return false
            }
            ++i
        }
        return true
    }
}*/
